home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / Apache 1.0 / src / http_main.c < prev    next >
Text File  |  1995-12-04  |  27KB  |  1,042 lines

  1.  
  2. /* ====================================================================
  3.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer. 
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in
  14.  *    the documentation and/or other materials provided with the
  15.  *    distribution.
  16.  *
  17.  * 3. All advertising materials mentioning features or use of this
  18.  *    software must display the following acknowledgment:
  19.  *    "This product includes software developed by the Apache Group
  20.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  21.  *
  22.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  23.  *    endorse or promote products derived from this software without
  24.  *    prior written permission.
  25.  *
  26.  * 5. Redistributions of any form whatsoever must retain the following
  27.  *    acknowledgment:
  28.  *    "This product includes software developed by the Apache Group
  29.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  32.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  35.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  42.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  43.  * ====================================================================
  44.  *
  45.  * This software consists of voluntary contributions made by many
  46.  * individuals on behalf of the Apache Group and was originally based
  47.  * on public domain software written at the National Center for
  48.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  49.  * For more information on the Apache Group and the Apache HTTP server
  50.  * project, please see <http://www.apache.org/>.
  51.  *
  52.  */
  53.  
  54.  
  55. /*
  56.  * httpd.c: simple http daemon for answering WWW file requests
  57.  *
  58.  * 
  59.  * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3)
  60.  * 
  61.  * 03-06-95  blong
  62.  *  changed server number for child-alone processes to 0 and changed name
  63.  *   of processes
  64.  *
  65.  * 03-10-95  blong
  66.  *     Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu) 
  67.  *    including set group before fork, and call gettime before to fork
  68.  *     to set up libraries.
  69.  *
  70.  * 04-14-95  rst / rh
  71.  *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
  72.  *      Apache server, and also to have child processes do accept() directly.
  73.  *
  74.  * April-July '95 rst
  75.  *      Extensive rework for Shambhala.
  76.  */
  77.  
  78.  
  79. #define CORE_PRIVATE
  80.  
  81. #include "httpd.h"
  82. #include "http_main.h"
  83. #include "http_log.h"
  84. #include "http_config.h"    /* for read_config */
  85. #include "http_protocol.h"    /* for read_request */
  86. #include "http_request.h"    /* for process_request */
  87. #include "http_conf_globals.h"
  88. #include "scoreboard.h"
  89. #include <setjmp.h>
  90.  
  91. /*
  92.  * Actual definitions of config globals... here because this is
  93.  * for the most part the only code that acts on 'em.  (Hmmm... mod_main.c?)
  94.  */
  95.  
  96. int standalone;
  97. uid_t user_id;
  98. char *user_name;
  99. gid_t group_id;
  100. int max_requests_per_child;
  101. char *pid_fname;
  102. char *server_argv0;
  103. struct in_addr bind_address;
  104. int daemons_to_start;
  105. int daemons_min_free;
  106. int daemons_max_free;
  107. int daemons_limit;
  108.  
  109. char server_root[MAX_STRING_LEN];
  110. char server_confname[MAX_STRING_LEN];
  111.  
  112. /* *Non*-shared http_main globals... */
  113.  
  114. server_rec *server_conf;
  115. JMP_BUF jmpbuffer;
  116. JMP_BUF restart_buffer;
  117. int sd;
  118. pid_t pgrp;
  119.  
  120. /* one_process --- debugging mode variable; can be set from the command line
  121.  * with the -X flag.  If set, this gets you the child_main loop running
  122.  * in the process which originally started up (no detach, no make_child),
  123.  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
  124.  * early in standalone_main; just continue through.  This is the server
  125.  * trying to kill off any child processes which it might have lying
  126.  * around --- Shambhala doesn't keep track of their pids, it just sends
  127.  * SIGHUP to the process group, ignoring it in the root process.
  128.  * Continue through and you'll be fine.).
  129.  */
  130.  
  131. int one_process = 0;
  132.  
  133. #ifdef FCNTL_SERIALIZED_ACCEPT
  134. static struct flock lock_it = { F_WRLCK, 0, 0, 0 };
  135. static struct flock unlock_it = { F_UNLCK, 0, 0, 0 };
  136.  
  137. static int lock_fd=-1;
  138.  
  139. /*
  140.  * Initialise mutex lock.
  141.  * Must be safe to call this on a restart.
  142.  */
  143. void
  144. accept_mutex_init(pool *p)
  145. {
  146.     char lock_fname[30];
  147.  
  148.     strcpy(lock_fname, "/usr/tmp/htlock.XXXXXX");
  149.     
  150.     if (mktemp(lock_fname) == NULL || lock_fname[0] == '\0')
  151.     {
  152.     fprintf (stderr, "Cannot assign name to lock file!\n");
  153.     exit (1);
  154.     }
  155.  
  156.     lock_fd = popenf(p, lock_fname, O_CREAT | O_WRONLY, 0644);
  157.     if (lock_fd == -1)
  158.     {
  159.     perror ("open");
  160.     fprintf (stderr, "Cannot open lcok file\n");
  161.     exit (1);
  162.     }
  163.     unlink(lock_fname);
  164. }
  165.  
  166. void accept_mutex_on()
  167. {
  168.     int ret;
  169.     
  170.     while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR)
  171.     continue;
  172.  
  173.     if (ret < 0) {
  174.     log_error ("Unknown failure grabbing accept lock.  Exiting!",
  175.            server_conf);
  176.     exit(1);
  177.     }
  178. }
  179.  
  180. void accept_mutex_off()
  181. {
  182.     if (fcntl (lock_fd, F_SETLKW, &unlock_it) < 0)
  183.     {
  184.     log_error("Error freeing accept lock.  Exiting!", server_conf);
  185.     exit(1);
  186.     }
  187. }
  188. #else
  189. /* Default --- no serialization.  Other methods *could* go here,
  190.  * as #elifs...
  191.  */
  192. #define accept_mutex_init(x)
  193. #define accept_mutex_on()
  194. #define accept_mutex_off()
  195. #endif
  196.  
  197. void usage(char *bin)
  198. {
  199.     fprintf(stderr,"Usage: %s [-d directory] [-f file] [-v]\n",bin);
  200.     fprintf(stderr,"-d directory : specify an alternate initial ServerRoot\n");
  201.     fprintf(stderr,"-f file : specify an alternate ServerConfigFile\n");
  202.     exit(1);
  203. }
  204.  
  205. /*****************************************************************
  206.  *
  207.  * Timeout handling.  DISTINCTLY not thread-safe, but all this stuff
  208.  * has to change for threads anyway.  Note that this code allows only
  209.  * one timeout in progress at a time...
  210.  */
  211.  
  212. static conn_rec *current_conn;
  213. static request_rec *timeout_req;
  214. static char *timeout_name;
  215. static int alarms_blocked = 0;
  216. static int alarm_pending = 0;
  217.  
  218. void abort_connection (conn_rec *);
  219.  
  220. void timeout(sig)            /* Also called on SIGPIPE */
  221. int sig;
  222. {
  223.     char errstr[MAX_STRING_LEN];
  224.  
  225.     if (alarms_blocked) {
  226.     alarm_pending = 1;
  227.     return;
  228.     }
  229.     
  230.     if (!current_conn) {
  231. #ifdef NEXT
  232.     longjmp(jmpbuffer,1);
  233. #else
  234.     siglongjmp(jmpbuffer,1);
  235. #endif
  236.     }
  237.     
  238.     sprintf(errstr,"%s timed out for %s",
  239.         timeout_name ? timeout_name : "request",
  240.         current_conn->remote_name);
  241.     
  242.     log_error(errstr, current_conn->server);
  243.       
  244.     if (timeout_req) {
  245.     /* Someone has asked for this transaction to just be aborted
  246.      * if it times out...
  247.      */
  248.     
  249.     request_rec *log_req = timeout_req;
  250.     
  251.     while (log_req->main || log_req->prev) {
  252.         /* Get back to original request... */
  253.         if (log_req->main) log_req = log_req->main;
  254.         else log_req = log_req->prev;
  255.     }
  256.     
  257.     log_transaction(log_req);
  258.  
  259.     pfclose (timeout_req->connection->pool,
  260.          timeout_req->connection->client);
  261.     pfclose (timeout_req->connection->pool,
  262.              timeout_req->connection->request_in);
  263.     
  264.     if (!standalone) exit(0);
  265. #ifdef NEXT
  266.     longjmp(jmpbuffer,1);
  267. #else
  268.     siglongjmp(jmpbuffer,1);
  269. #endif
  270.     }
  271.     else {
  272.     abort_connection (current_conn);
  273.     }
  274. }
  275.  
  276. /*
  277.  * These two called from alloc.c to protect its critical sections...
  278.  * Note that they can nest (as when destroying the sub_pools of a pool
  279.  * which is itself being cleared); we have to support that here.
  280.  */
  281.  
  282. void block_alarms() {
  283.     ++alarms_blocked;
  284. }
  285.  
  286. void unblock_alarms() {
  287.     --alarms_blocked;
  288.     if (alarms_blocked == 0 && alarm_pending) {
  289.     alarm_pending = 0;
  290.     timeout(0);
  291.     }
  292. }
  293.  
  294. void hard_timeout (char *name, request_rec *r)
  295. {
  296.     timeout_req = r;
  297.     timeout_name = name;
  298.     
  299.     signal(SIGALRM,(void (*)())timeout);
  300.     alarm (r->server->timeout);
  301. }
  302.  
  303. void soft_timeout (char *name, request_rec *r)
  304. {
  305.     timeout_name = name;
  306.     
  307.     signal(SIGALRM,(void (*)())timeout);
  308.     alarm (r->server->timeout);
  309. }
  310.  
  311. void kill_timeout (request_rec *dummy) {
  312.     alarm (0);
  313.     timeout_req = NULL;
  314.     timeout_name = NULL;
  315. }
  316.  
  317. /*****************************************************************
  318.  *
  319.  * Dealing with the scoreboard... a lot of these variables are global
  320.  * only to avoid getting clobbered by the longjmp() that happens when
  321.  * a hard timeout expires...
  322.  *
  323.  * We begin with routines which deal with the file itself... 
  324.  */
  325.  
  326. static short_score scoreboard_image[HARD_SERVER_MAX];
  327. static char scoreboard_fname[] = "/tmp/htstatus.XXXXXX";
  328. static int have_scoreboard_fname = 0;
  329. static int scoreboard_fd;
  330.  
  331. static int force_write (int fd, char *buffer, int bufsz)
  332. {
  333.     int rv, orig_sz = bufsz;
  334.     
  335.     do {
  336.     rv = write (fd, buffer, bufsz);
  337.     if (rv > 0) {
  338.         buffer += rv;
  339.         bufsz -= rv;
  340.     }
  341.     } while (rv > 0 && bufsz > 0);
  342.  
  343.     return rv < 0? rv : orig_sz - bufsz;
  344. }
  345.  
  346. static int force_read (int fd, char *buffer, int bufsz)
  347. {
  348.     int rv, orig_sz = bufsz;
  349.     
  350.     do {
  351.     rv = read (fd, buffer, bufsz);
  352.     if (rv > 0) {
  353.         buffer += rv;
  354.         bufsz -= rv;
  355.     }
  356.     } while (rv > 0 && bufsz > 0);
  357.     
  358.     return rv < 0? rv : orig_sz - bufsz;
  359. }
  360.  
  361. void reinit_scoreboard (pool *p)
  362. {
  363.     if (!have_scoreboard_fname && (mktemp(scoreboard_fname) == NULL ||
  364.                    scoreboard_fname[0] == '\0')) {
  365.     fprintf (stderr, "Cannot assign name to scoreboard file!\n");
  366.     exit (1);
  367.     }
  368.     
  369.     have_scoreboard_fname = 1;
  370.     
  371.     scoreboard_fd = popenf(p, scoreboard_fname, O_CREAT|O_RDWR, 0644);
  372.     if (scoreboard_fd == -1)
  373.     {
  374.     fprintf (stderr, "Cannot open scoreboard file:\n");
  375.     perror (scoreboard_fname);
  376.     exit (1);
  377.     }
  378.  
  379.     memset ((char*)scoreboard_image, 0, sizeof(scoreboard_image));
  380.     force_write (scoreboard_fd, (char*)scoreboard_image,
  381.          sizeof(scoreboard_image));
  382. }
  383.  
  384. void reopen_scoreboard (pool *p)
  385. {
  386.     if (scoreboard_fd != -1) pclosef (p, scoreboard_fd);
  387.     
  388.     scoreboard_fd = popenf(p, scoreboard_fname, O_CREAT|O_RDWR, 0666);
  389.     if (scoreboard_fd == -1)
  390.     {
  391.     fprintf (stderr, "Cannot open scoreboard file:\n");
  392.     perror (scoreboard_fname);
  393.     exit (1);
  394.     }
  395. }
  396.  
  397. void cleanup_scoreboard ()
  398. {
  399.     unlink (scoreboard_fname);
  400. }
  401.  
  402. /* Routines called to deal with the scoreboard image
  403.  * --- note that we do *not* need write locks, since update_child_status
  404.  * only updates a *single* record in place, and only one process writes to
  405.  * a given scoreboard slot at a time (either the child process owning that
  406.  * slot, or the parent, noting that the child has died).
  407.  *
  408.  * As a final note --- setting the score entry to getpid() is always safe,
  409.  * since when the parent is writing an entry, it's only noting SERVER_DEAD
  410.  * anyway.
  411.  */
  412.  
  413. void sync_scoreboard_image ()
  414. {
  415.     lseek (scoreboard_fd, 0L, 0);
  416.     force_read (scoreboard_fd, (char*)scoreboard_image,
  417.         sizeof(scoreboard_image));
  418. }
  419.  
  420. void update_child_status (int child_num, int status)
  421. {
  422.     short_score new_score_rec;
  423.     new_score_rec.pid = getpid();
  424.     new_score_rec.status = status;
  425.  
  426.     lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
  427.     force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
  428. }
  429.  
  430. int count_idle_servers ()
  431. {
  432.     int i;
  433.     int res = 0;
  434.  
  435.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  436.     if (scoreboard_image[i].status == SERVER_READY)
  437.         ++res;
  438.  
  439.     return res;
  440. }
  441.  
  442. int find_free_child_num ()
  443. {
  444.     int i;
  445.  
  446.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  447.     if (scoreboard_image[i].status == SERVER_DEAD)
  448.         return i;
  449.  
  450.     return -1;
  451. }
  452.  
  453. int find_child_by_pid (int pid)
  454. {
  455.     int i;
  456.  
  457.     for (i = 0; i < HARD_SERVER_MAX; ++i)
  458.     if (scoreboard_image[i].pid == pid)
  459.         return i;
  460.  
  461.     return -1;
  462. }
  463.  
  464. void reclaim_child_processes ()
  465. {
  466.     int i, status;
  467.     int my_pid = getpid();
  468.  
  469.     sync_scoreboard_image();
  470.     for (i = 0; i < HARD_SERVER_MAX; ++i) {
  471.     int pid = scoreboard_image[i].pid;
  472.  
  473.     if (pid != my_pid && pid != 0)
  474.         waitpid (scoreboard_image[i].pid, &status, 0);
  475.     }
  476. }
  477.  
  478. /* Finally, this routine is used by the caretaker process to wait for
  479.  * a while...
  480.  */
  481.  
  482. static jmp_buf wait_timeout_buf;
  483. static int wait_or_timeout_retval = -1;
  484.  
  485. static void longjmp_out_of_alarm (int sig) {
  486.     longjmp (wait_timeout_buf, 1);
  487. }
  488.  
  489. int wait_or_timeout (int *status)
  490. {
  491.     wait_or_timeout_retval = -1;
  492.     
  493.     if (setjmp(wait_timeout_buf) != 0) {
  494.     errno = ETIMEDOUT;
  495.     alarm(0);
  496.     return wait_or_timeout_retval;
  497.     }
  498.     
  499.     signal (SIGALRM, longjmp_out_of_alarm);
  500.     alarm(1);
  501. #if defined(NEXT)
  502.     wait_or_timeout_retval = wait((union wait *)status);
  503. #else
  504.     wait_or_timeout_retval = wait(status);
  505. #endif
  506.     alarm(0);
  507.     return wait_or_timeout_retval;
  508. }
  509.  
  510.  
  511. /*****************************************************************
  512.  * Here follows a long bunch of generic server bookkeeping stuff...
  513.  */
  514.  
  515. void detach()
  516. {
  517.     int x;
  518.  
  519.     chdir("/");
  520.     if((x = fork()) > 0)
  521.         exit(0);
  522.     else if(x == -1) {
  523.         fprintf(stderr,"httpd: unable to fork new process\n");
  524.         perror("fork");
  525.         exit(1);
  526.     }
  527. #ifndef NO_SETSID
  528.     if((pgrp=setsid()) == -1) {
  529.         fprintf(stderr,"httpd: setsid failed\n");
  530.         perror("setsid");
  531.         exit(1);
  532.     }
  533. #else
  534. #if defined(NEXT)
  535.     if(setpgrp(0,getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
  536.         fprintf(stderr,"httpd: setpgrp or getpgrp failed\n");
  537.         perror("setpgrp");
  538.         exit(1);
  539.     }
  540. #else
  541.     if((pgrp=setpgrp(getpid(),0)) == -1) {
  542.         fprintf(stderr,"httpd: setpgrp failed\n");
  543.         perror("setpgrp");
  544.         exit(1);
  545.     }
  546. #endif    
  547. #endif
  548. }
  549.  
  550. void sig_term() {
  551.     log_error("httpd: caught SIGTERM, shutting down", server_conf);
  552.     cleanup_scoreboard();
  553. #ifndef NO_KILLPG
  554.     killpg(pgrp,SIGKILL);
  555. #else
  556.     kill(-pgrp,SIGKILL);
  557. #endif
  558.     shutdown(sd,2);
  559.     close(sd);
  560.     exit(1);
  561. }
  562.  
  563. void bus_error() {
  564.     log_error("httpd: caught SIGBUS, dumping core", server_conf);
  565.     chdir(server_root);
  566.     abort();         
  567.     exit(1);
  568. }
  569.  
  570. void seg_fault() {
  571.     log_error("httpd: caught SIGSEGV, dumping core", server_conf);
  572.     chdir(server_root);
  573.     abort();
  574.     exit(1);
  575. }
  576.  
  577. void just_die()            /* SIGHUP to child process??? */
  578. {
  579.     exit (0);
  580. }
  581.  
  582. /* Reset group privileges, after rereading the config files
  583.  * (our uid may have changed, and if so, we want the new perms).
  584.  *
  585.  * Don't reset the uid yet --- we do that only in the child process,
  586.  * so as not to lose any root privs.  But we can set the group stuff
  587.  * now, once, as opposed to once per each new child.
  588.  *
  589.  * Note that we use the username as set in the config files, rather than
  590.  * the lookup of to uid --- the same uid may have multiple passwd entries,
  591.  * with different sets of groups for each.
  592.  */
  593.   
  594. static void set_group_privs()
  595. {
  596.   if(!geteuid()) {
  597.     char *name;
  598.   
  599.     /* Get username if passed as a uid */
  600.     
  601.     if (user_name[0] == '#') {
  602.       struct passwd* ent;
  603.       uid_t uid=atoi(&user_name[1]);
  604.  
  605.       if ((ent = getpwuid(uid)) == NULL) {
  606.      log_error("couldn't determine user name from uid", server_conf);
  607.      exit(1);
  608.       }
  609.       
  610.       name = ent->pw_name;
  611.     } else name = user_name;
  612.  
  613.     /* Reset `groups' attributes. */
  614.     
  615.     if (initgroups(name, group_id) == -1) {
  616.         log_error ("unable to set groups", server_conf);
  617.     exit (1);
  618.     }
  619.  
  620.     if (setgid(group_id) == -1) {
  621.         log_error ("unable to set group id", server_conf);
  622.     exit (1);
  623.     }
  624.   }
  625. }
  626.  
  627. void restart() {
  628.     signal (SIGALRM, SIG_IGN);
  629.     alarm (0);
  630. #ifdef NEXT
  631.     longjmp(restart_buffer,1);
  632. #else
  633.     siglongjmp(restart_buffer,1);
  634. #endif
  635. }
  636.  
  637. void set_signals() {
  638.     if(!one_process)
  639.     {
  640.         signal(SIGSEGV,(void (*)())seg_fault);
  641.         signal(SIGBUS,(void (*)())bus_error);
  642.     }
  643.     signal(SIGTERM,(void (*)())sig_term);
  644.     signal(SIGHUP,(void (*)())restart);
  645. }
  646.  
  647. /*****************************************************************
  648.  * Connection structures and accounting...
  649.  * Should these be global?  Only to this file, at least...
  650.  */
  651.  
  652. pool *pconf;            /* Pool for config stuff */
  653. pool *ptrans;            /* Pool for per-transaction stuff */
  654.  
  655. server_rec *find_virtual_server (struct in_addr server_ip, server_rec *server)
  656. {
  657.     server_rec *virt;
  658.  
  659.     for (virt = server->next; virt; virt = virt->next)
  660.     if (virt->host_addr.s_addr == server_ip.s_addr)
  661.         return virt;
  662.  
  663.     return server;
  664. }
  665.  
  666. void default_server_hostnames(server_rec *s)
  667. {
  668.     /* Main host first */
  669.     
  670.     if (!s->server_hostname)
  671.     s->server_hostname = get_local_host(pconf);
  672.  
  673.     /* Then virtual hosts */
  674.     
  675.     for (s = s->next; s; s = s->next)
  676.     if (!s->server_hostname) {
  677.         struct hostent *h = gethostbyaddr ((char *)&(s->host_addr),
  678.                            sizeof (struct in_addr),
  679.                            AF_INET);
  680.         if (h != NULL) {
  681.         s->server_hostname = pstrdup (pconf, (char *)h->h_name);
  682.         }
  683.     }
  684. }
  685.     
  686. void abort_connection (conn_rec *c)
  687. {
  688.     /* Make sure further I/O DOES NOT HAPPEN */
  689.     shutdown (fileno (c->client), 2);
  690.     signal (SIGPIPE, SIG_IGN);    /* Ignore further complaints */
  691.     c->aborted = 1;
  692. }
  693.  
  694. conn_rec *new_connection (pool *p, server_rec *server, FILE *in, FILE *out,
  695.               const struct sockaddr_in *saddr)
  696. {
  697.     conn_rec *conn = (conn_rec *)pcalloc (p, sizeof(conn_rec));
  698.     
  699.     /* Get a connection structure, and initialize what fields we can
  700.      * (the rest are zeroed out by pcalloc).
  701.      */
  702.     
  703.     conn = (conn_rec *)pcalloc(p, sizeof(conn_rec));
  704.     
  705.     conn->pool = p;
  706.     conn->server = find_virtual_server (saddr->sin_addr, server);
  707.     conn->client = out;
  708.     conn->request_in = in;
  709.     
  710.     get_remote_host(conn);
  711.     
  712.     return conn;
  713. }
  714.  
  715. /*****************************************************************
  716.  * Child process main loop.
  717.  * The following vars are static to avoid getting clobbered by longjmp();
  718.  * they are really private to child_main.
  719.  */
  720.  
  721. static int csd;
  722. static int dupped_csd;
  723. static int requests_this_child;
  724. static int child_num;
  725.  
  726. void child_main(int child_num_arg)
  727. {
  728.     int clen;
  729.     struct sockaddr sa_server;
  730.     struct sockaddr sa_client;
  731.  
  732. #ifdef ULTRIX_BRAIN_DEATH
  733.     extern char *rfc931();
  734. #else
  735.     extern char *rfc931 (struct sockaddr_in *, struct sockaddr_in *);
  736. #endif
  737.  
  738.     csd = -1;
  739.     dupped_csd = -1;
  740.     child_num = child_num_arg;
  741.     requests_this_child = 0;
  742.     reopen_scoreboard (pconf);
  743.     update_child_status (child_num, SERVER_READY);
  744.  
  745.     /* Only try to switch if we're running as root */
  746.     if(!geteuid() && setuid(user_id) == -1) {
  747.         log_error ("unable to change uid", server_conf);
  748.     exit (1);
  749.     }
  750.  
  751. #ifdef NEXT
  752.     setjmp(jmpbuffer);
  753. #else
  754.     sigsetjmp(jmpbuffer,1);
  755. #endif
  756.     signal(SIGURG, timeout);
  757.  
  758.     while (1) {
  759.     FILE *conn_in, *conn_out;
  760.     request_rec *r;
  761.       
  762.         alarm(0);        /* Cancel any outstanding alarms. */
  763.         timeout_req = NULL;    /* No request in progress */
  764.     current_conn = NULL;
  765.         signal(SIGPIPE, timeout);  
  766.     
  767.     clear_pool (ptrans);
  768.     
  769.     sync_scoreboard_image();
  770.     
  771.     if ((count_idle_servers() >= daemons_max_free)
  772.         || (max_requests_per_child > 0
  773.             && ++requests_this_child >= max_requests_per_child))
  774.     {
  775.         exit(0);
  776.     }
  777.  
  778.     clen=sizeof(sa_client);
  779.     update_child_status (child_num, SERVER_READY);
  780.     
  781.     accept_mutex_on();  /* Lock around "accept", if necessary */
  782.     
  783.     while ((csd=accept(sd, &sa_client, &clen)) == -1) 
  784.            if (errno != EINTR) 
  785.         log_error("socket error: accept failed", server_conf);
  786.  
  787.     accept_mutex_off(); /* unlock after "accept" */
  788.  
  789.     clen = sizeof(sa_server);
  790.     if(getsockname(csd, &sa_server, &clen) < 0) {
  791.         log_error("getsockname: failed", server_conf);
  792.         continue;
  793.     }
  794.     
  795.     dupped_csd = csd;
  796. #if defined(AUX) || defined(SCO)
  797.     if ((dupped_csd = dup(csd)) < 0) {
  798.         log_error("couldn't duplicate csd", server_conf);
  799.         dupped_csd = csd;    /* Oh well... */
  800.     }
  801. #endif
  802.     update_child_status (child_num, SERVER_BUSY);
  803.     conn_in = pfdopen (ptrans, csd, "r");
  804.     conn_out = pfdopen (ptrans, dupped_csd, "w");
  805.  
  806.     current_conn = new_connection (ptrans, server_conf, conn_in, conn_out,
  807.                        (struct sockaddr_in *)&sa_server);
  808.  
  809.     if (current_conn->server->do_rfc931)
  810.         current_conn->remote_logname = 
  811.         rfc931((struct sockaddr_in *)&sa_client,
  812.                (struct sockaddr_in *)&sa_server);
  813.     
  814.     r = read_request (current_conn);
  815.     if (r) process_request (r); /* else premature EOF --- ignore */
  816.         
  817.     if (bytes_in_pool (ptrans) > 80000) {
  818.         char errstr[MAX_STRING_LEN];
  819.         sprintf (errstr, "Memory hog alert: allocated %ld bytes for %s",
  820.                  bytes_in_pool (ptrans), r->the_request);
  821.             log_error (errstr, r->server);
  822.         }
  823.         
  824.     fflush (conn_out);
  825.     pfclose (ptrans,conn_in);
  826.     pfclose (ptrans,conn_out);
  827.     }    
  828. }
  829.  
  830. void make_child(server_rec *server_conf, int child_num)
  831. {
  832.     int pid;
  833.  
  834.     if (one_process) {
  835.     signal (SIGHUP, (void (*)())just_die);
  836.     signal (SIGTERM, (void (*)())just_die);
  837.     child_main (child_num);
  838.     }
  839.  
  840.     if ((pid = fork()) == -1) {
  841.     log_error("Unable to fork new process", server_conf);
  842.     return;
  843.     } 
  844.     
  845.     if (!pid) {
  846.     signal (SIGHUP, (void (*)())just_die);
  847.     signal (SIGTERM, (void (*)())just_die);
  848.     child_main (child_num);
  849.     }
  850. }
  851.  
  852. /*****************************************************************
  853.  * Executive routines.
  854.  */
  855.  
  856. static int keepalive_value = 1;  
  857. static int one = 1;
  858. static int num_children = 0;
  859.  
  860. void standalone_main(int argc, char **argv)
  861. {
  862.     struct sockaddr_in sa_server;
  863.  
  864.     standalone = 1;
  865.     sd = -1;
  866.     
  867.     if (!one_process) detach(); 
  868.     
  869. #ifdef NEXT
  870.     setjmp(restart_buffer);
  871. #else
  872.     sigsetjmp(restart_buffer,1);
  873. #endif
  874.  
  875.     signal (SIGHUP, SIG_IGN);    /* Until we're done (re)reading config */
  876.     
  877.     if(!one_process)
  878. #ifndef NO_KILLPG
  879.       killpg(pgrp,SIGHUP);    /* Kill 'em off */
  880. #else
  881.       kill(-pgrp,SIGHUP);
  882. #endif
  883.     
  884.     if (sd != -1) {
  885.     reclaim_child_processes(); /* Not when just starting up */
  886.     log_error ("SIGHUP received.  Attempting to restart", server_conf);
  887.     }
  888.     
  889.     clear_pool (pconf);
  890.     ptrans = make_sub_pool (pconf);
  891.     
  892.     server_conf = read_config(pconf, ptrans, server_confname); 
  893.     open_logs(server_conf, pconf);
  894.     set_group_privs();
  895.     accept_mutex_init(pconf);
  896.     reinit_scoreboard(pconf);
  897.     
  898.     default_server_hostnames (server_conf);
  899.  
  900.     if ((sd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  901.         fprintf(stderr,"httpd: could not get socket\n");
  902.         perror("socket");
  903.         exit(1);
  904.     }
  905.  
  906.     note_cleanups_for_fd (pconf, sd); /* arrange to close on exec or restart */
  907.     
  908.     if((setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(const char *)&one,sizeof(one)))
  909.        == -1) {
  910.         fprintf(stderr,"httpd: could not set socket option\n");
  911.         perror("setsockopt");
  912.         exit(1);
  913.     }
  914.     if((setsockopt(sd,SOL_SOCKET,SO_KEEPALIVE,(const void *)&keepalive_value,
  915.         sizeof(keepalive_value))) == -1) {
  916.         fprintf(stderr,"httpd: could not set socket option SO_KEEPALIVE\n"); 
  917.         perror("setsockopt"); 
  918.         exit(1); 
  919.     }
  920.  
  921.     memset((char *) &sa_server, 0, sizeof(sa_server));
  922.     sa_server.sin_family=AF_INET;
  923.     sa_server.sin_addr=bind_address;
  924.     sa_server.sin_port=htons(server_conf->port);
  925.     if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
  926.     if (bind_address.s_addr != htonl(INADDR_ANY))
  927.         fprintf(stderr,"httpd: could not bind to address %s port %d\n",
  928.             inet_ntoa(bind_address), server_conf->port);
  929.     else
  930.         fprintf(stderr,"httpd: could not bind to port %d\n",
  931.             server_conf->port);
  932.         perror("bind");
  933.         exit(1);
  934.     }
  935.     listen(sd, 512);
  936.  
  937.     set_signals();
  938.     log_pid(pconf, pid_fname);
  939.  
  940.     num_children = 0;
  941.     
  942.     if (daemons_max_free < daemons_min_free + 1) /* Don't thrash... */
  943.     daemons_max_free = daemons_min_free + 1;
  944.  
  945.     while (num_children < daemons_to_start) {
  946.     make_child(server_conf, num_children++);
  947.     }
  948.  
  949.     log_error ("Server configured -- resuming normal operations", server_conf);
  950.     
  951.     while (1) {
  952.     int status, child_slot;
  953.     int pid = wait_or_timeout(&status);
  954.     
  955.     if (pid >= 0) {
  956.         /* Child died... note that it's gone in the scoreboard. */
  957.         sync_scoreboard_image();
  958.         child_slot = find_child_by_pid (pid);
  959.         if (child_slot >= 0) update_child_status (child_slot, SERVER_DEAD);
  960.         }
  961.  
  962.     sync_scoreboard_image();
  963.     if ((count_idle_servers() < daemons_min_free)
  964.         && (child_slot = find_free_child_num()) >= 0
  965.         && child_slot <= daemons_limit)
  966.         make_child(server_conf, child_slot);
  967.     }
  968.  
  969. } /* standalone_main */
  970.  
  971. extern char *optarg;
  972. extern int optind;
  973.  
  974. int
  975. main(int argc, char *argv[])
  976. {
  977.     int c;
  978.  
  979.     init_alloc();
  980.     pconf = permanent_pool;
  981.     ptrans = make_sub_pool(pconf);
  982.     
  983.     server_argv0 = argv[0];
  984.     strcpy (server_root, HTTPD_ROOT);
  985.     strcpy (server_confname, SERVER_CONFIG_FILE);
  986.  
  987.     while((c = getopt(argc,argv,"Xd:f:v")) != -1) {
  988.         switch(c) {
  989.           case 'd':
  990.             strcpy (server_root, optarg);
  991.             break;
  992.           case 'f':
  993.             strcpy (server_confname, optarg);
  994.             break;
  995.           case 'v':
  996.             printf("Server version %s.\n",SERVER_VERSION);
  997.             exit(1);
  998.       case 'X':
  999.         ++one_process;    /* Weird debugging mode. */
  1000.         break;
  1001.           case '?':
  1002.             usage(argv[0]);
  1003.         }
  1004.     }
  1005.  
  1006.     setup_prelinked_modules();
  1007.     
  1008.     server_conf = read_config (pconf, ptrans, server_confname);
  1009.     
  1010.     if(standalone) {
  1011.         clear_pool (pconf);    /* standalone_main rereads... */
  1012.         standalone_main(argc, argv);
  1013.     }
  1014.     else {
  1015.         conn_rec *conn;
  1016.     request_rec *r;
  1017.     struct sockaddr sa_server;
  1018.       
  1019.     open_logs(server_conf, pconf);
  1020.     set_group_privs();
  1021.     default_server_hostnames (server_conf);
  1022.  
  1023.         user_id = getuid();
  1024.         group_id = getgid();
  1025.  
  1026.     c = sizeof(sa_server);
  1027.     if(getsockname(csd, &sa_server, &c) < 0) {
  1028.         perror("getsockname");
  1029.         fprintf(stderr, "Error getting local address\n");
  1030.         exit(1);
  1031.     }
  1032.     server_conf->port =ntohs(((struct sockaddr_in *)&sa_server)->sin_port);
  1033.     conn = new_connection (ptrans, server_conf, stdin, stdout,
  1034.                    (struct sockaddr_in *)&sa_server);
  1035.     r = read_request (conn);
  1036.     if (r) process_request (r); /* else premature EOF (ignore) */
  1037.     }
  1038.     exit (0);
  1039. }
  1040.  
  1041.  
  1042.